package com.yeziji.security.aspect;

import com.yeziji.common.CommonErrorMsg;
import com.yeziji.common.base.UserOnlineBase;
import com.yeziji.common.context.OnlineContext;
import com.yeziji.constant.VariousStrPool;
import com.yeziji.exception.ApiException;
import com.yeziji.security.common.SecurityToken;
import com.yeziji.security.common.SecurityTokenContext;
import com.yeziji.security.common.SecurityUserBase;
import com.yeziji.security.utils.JwtUtils;
import com.yeziji.utils.ServletUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * aop 拦截 {@link com.yeziji.security.service.DynamicSecurityUserService} 的执行
 *
 * @author hwy
 * @since 2024/09/29 15:48
 **/
@Slf4j
@Aspect
@Component
public class DynamicSecurityUserAspect {
    @Resource
    private HttpServletRequest request;
    @Resource
    private HttpServletResponse response;

    @Around(("execution(* com.yeziji.security.service.DynamicSecurityUserService.login(..))"))
    public Object loginHandler(ProceedingJoinPoint pjp) {
        try {
            long expired = 0L;
            Object[] args = pjp.getArgs();
            for (Object arg : args) {
                if (arg instanceof SecurityUserBase) {
                    SecurityUserBase securityUser = (SecurityUserBase) arg;
                    expired = securityUser.getExpired();
                    if (expired <= 0) {
                        log.warn("token expired time {} <= 0 so the system auto assigns a default value of: {}", expired, JwtUtils.DEFAULT_EXPIRED);
                        expired = JwtUtils.DEFAULT_EXPIRED;
                    }
                }
            }
            Object proceed = pjp.proceed();
            if (proceed instanceof UserOnlineBase) {
                UserOnlineBase loginInfo = (UserOnlineBase) proceed;
                // 赋值当前登录信息
                loginInfo.setLoginTime(new Date());
                loginInfo.setIp(ServletUtils.getIpAddress(request));
                // 返回 token
                SecurityToken securityToken = JwtUtils.newSecurityToken(loginInfo, expired);
                response.setHeader(VariousStrPool.HttpHeaders.AUTHORIZATION, securityToken.getOriginalToken());
                response.setHeader(VariousStrPool.HttpHeaders.REFRESH_AUTHORIZATION, securityToken.getRefreshToken());
                // 保存 originalToken
                SecurityTokenContext.put(securityToken.getOriginalToken(), securityToken);
            }
            return proceed;
        } catch (Throwable e) {
            if (e instanceof ApiException) {
                throw new ApiException(((ApiException) e).getErrorEnum());
            }
            log.error("exception: {}", e.getMessage(), e);
            throw new ApiException(CommonErrorMsg.SYSTEM_ERROR);
        }
    }

    @Around(("execution(* com.yeziji.security.service.DynamicSecurityUserService.logout(..))"))
    public Object logoutHandler(ProceedingJoinPoint pjp) {
        try {
            Object proceed = pjp.proceed();
            SecurityTokenContext.deprecated(OnlineContext.getToken());
            return proceed;
        } catch (Exception e) {
            log.warn("logout remove context err: {}", e.getMessage(), e);
            return false;
        } catch (Throwable e) {
            throw new ApiException(CommonErrorMsg.SYSTEM_ERROR);
        }
    }
}
